package se.webbzon.boltzmann.game.object.item;

import java.util.Collection;

import se.webbzon.boltzmann.collector.Collector;
import se.webbzon.boltzmann.environment.AbstractEnvironment;
import se.webbzon.boltzmann.game.environment.GameEnvironment;
import se.webbzon.boltzmann.game.object.player.AbstractPlayerCharacter;
import se.webbzon.boltzmann.game.region.RegionObject;
import se.webbzon.boltzmann.item.AbstractItem;
import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldeditor.DeflatableWorldObject;
import se.webbzon.oschi01.worldeditor.WorldObjectDeflation;
import se.webbzon.oschi01.worldobject.WorldObject;
import se.webbzon.oschi01.worldobject.WorldStaticObject;
import se.webbzon.oschi01.worldobject.appearance.AbstractAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.SimpleAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.XYPlaneAppearance3D;

public class GameItem extends WorldStaticObject implements RegionObject, DeflatableWorldObject {
	
	// The name of this deflatable world object
	public static final String worldObjectName = "gameItem";
	
	// The maximal distance between the item and the player to pick up the item
	private static final int pickupDistance = 16;
	
	// The environment associated with this game item
	private final AbstractEnvironment env;
	
	// The shadow of the game item
	private final GameItemShadow shadow;
	
	// A player collector
	private Collector<AbstractPlayerCharacter> players;
	
	// The region object id
	private long id;
	
	// The item associated with this game item
	private AbstractItem item;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public GameItem(AbstractEnvironment env, long id, AbstractItem item) {
		super(	WorldObject.onCreate + WorldObject.onStep + WorldObject.onDestroy,
				createAppearance(item));
		this.env = env;
		this.id = id;
		setItem(item);
		shadow = new GameItemShadow(this);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Sets the item associated with this game item. **/
	public void setItem(AbstractItem item) {
		this.item = item;
		SimpleAppearance3D appearance = (SimpleAppearance3D) getAppearance();
		if (item != null)
			appearance.setTextureSet(item.getTextureSet());
		else
			appearance.setTextureSet(Resources.getTextureSet("misc_unknown"));
	}
	
	/** Returns the item associated with this game item. **/
	public AbstractItem getItem() {
		return item;
	}
	
	@Override public void onCreate(WorldArea world) {
		shadow.launch(world);
		players = Collector.getCollector(world, AbstractPlayerCharacter.class);
	}
	
	@Override public void onStep(WorldArea world) {
		Collection<AbstractPlayerCharacter> playerCollection = players.getInstances();
		synchronized (playerCollection) {
			for (AbstractPlayerCharacter player : playerCollection) {
				if (distanceTo(player) <= pickupDistance) {
					if (player.getPlayer().getInventory().addItem(item)) {
						
						if (env instanceof GameEnvironment)
							((GameEnvironment) env).addGamePersistence(this);
						
						world.destroyInstance(this);
					}
				}
			}
		}
	}
	
	@Override public void onDestroy(WorldArea world) {
		shadow.terminate(world);
		players = null;
	}
	
	@Override public String getName() {
		return worldObjectName;
	}

	@Override public WorldObjectDeflation getDeflation() {
		return new GameItemDeflation(0,this);
	}

	@Override public long getId() {
		return id;
	}

	@Override public void setId(long id) {
		this.id = id;
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Creates a new appearance for this game item. **/
	private static final AbstractAppearance3D createAppearance(AbstractItem item) {
		XYPlaneAppearance3D appearance = new XYPlaneAppearance3D();
		appearance.setTextureSpeed(1);
		return appearance;
	}

}
